/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.tbp.persitence.dao.impl;

import br.com.tbp.exception.PersistenciaException;
import br.com.tbp.model.domain.financeiro.CondicaoConta;
import br.com.tbp.model.domain.financeiro.Conta;
import br.com.tbp.model.domain.financeiro.TipoConta;
import br.com.tbp.persitence.GerenciadorDeConexao;
import br.com.tbp.persitence.GerenciadorDeQuery;
import br.com.tbp.persitence.dao.ContaDao;
import br.com.tbp.utils.DateUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @author Diego
 */
public class ContaDaoImpl implements ContaDao {

    private Connection conn = null;
    private PreparedStatement pr = null;
    private ResultSet rs = null;

    public void adicionar(Conta c) throws PersistenciaException {
        if (c == null) {
            throw new PersistenciaException("Não foi informado a conta a cadastrar.");
        }

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.insert"),
                    Statement.RETURN_GENERATED_KEYS);
            pr.setString(1, c.getDescricao());
            pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(c.getData()));
            pr.setDouble(3, c.getValor());
            pr.setString(4, c.getTipo().name());
            pr.setString(5, c.getCondicao().toString());
            pr.setString(6, c.getObs());
            pr.setBoolean(7, c.isQuitada());

            pr.executeUpdate();

            rs = pr.getGeneratedKeys();
            rs.next();
            long id = rs.getLong(1);
            c.setId(id);

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar a conta.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    public void editar(Conta c) throws PersistenciaException {
        if (c == null) {
            throw new PersistenciaException("Não foi informado a conta a editar.");
        }

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.update"));
            pr.setString(1, c.getDescricao());
            pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(c.getData()));
            pr.setDouble(3, c.getValor());
            pr.setString(4, c.getTipo().name());
            pr.setString(5, c.getCondicao().toString());
            pr.setString(6, c.getObs());
            pr.setBoolean(7, c.isQuitada());
            pr.setLong(8, c.getId());

            pr.executeUpdate();

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível editar a conta.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
    }

    public List<Conta> pesquisar(int mes, int ano) throws PersistenciaException {
        List<Conta> lista = new ArrayList<Conta>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.select.mesano"));
            pr.setInt(1, mes);
            pr.setInt(2, ano);
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    Conta c = this.criarConta(rs);
                    lista.add(c);
                }
            }

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar as contas de: ").append(mes).append("/").append(ano);
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    private Conta criarConta(ResultSet rs) throws PersistenciaException {
        Conta c = null;
        try {
            c = new Conta(rs.getLong("id_conta"));
            c.setDescricao(rs.getString("descricao"));
            c.setData(DateUtils.dataBancoDeDadosParaDataObjeto(rs.getDate("data")));
            c.setValor(new Double(rs.getDouble("valor")));
            c.setTipo(TipoConta.valueOf(rs.getString("tipo")));
            c.setCondicao(CondicaoConta.valueOf(rs.getString("condicao")));
            c.setObs(rs.getString("obs"));
            c.setQuitada(rs.getBoolean("quitada"));

        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados da conta.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return c;
    }

    public boolean excluir(Conta c) throws PersistenciaException {
        if (c == null) {
            throw new PersistenciaException("Não foi informado a conta a excluir.");
        }
        boolean sucesso = false;

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.delete"));
            pr.setLong(1, c.getId());

            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir a conta.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    public List<Conta> pesquisarPor(String descricao, int mes, int ano) throws PersistenciaException {
        List<Conta> lista = new ArrayList<Conta>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.select.descricao"));
            pr.setString(1, "%" + descricao + "%");
            pr.setInt(2, mes);
            pr.setInt(3, ano);
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    Conta c = this.criarConta(rs);
                    lista.add(c);
                }
            }

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar as contas de: ").append(mes).append("/").append(ano);
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Conta> pesquisarPor(Date data) throws PersistenciaException {
        List<Conta> lista = new ArrayList<Conta>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.select.data"));
            pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(data));
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    Conta c = this.criarConta(rs);
                    lista.add(c);
                }
            }

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar as contas.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Conta> pesquisarPor(Double valor, int mes, int ano) throws PersistenciaException {
        List<Conta> lista = new ArrayList<Conta>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("conta.select.valor"));
            pr.setDouble(1, valor);
            pr.setInt(2, mes);
            pr.setInt(3, ano);
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    Conta c = this.criarConta(rs);
                    lista.add(c);
                }
            }

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar as contas.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }
}
